function [features_struct]=calc_features_reg(image,HSV,seg_map, reg_map,filters, norm_flag,reg_indices_cell,lines)

% This function calculates all features per region - location, texture, color, shape, geometry

% Function Inputs:
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% image - RGB image matrix.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% HSV - HSV image matrix.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% seg_map - map of segments.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% reg_map - map of regions.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% filters - filters to be used during calculating texture features. 
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% norm_flag - normalization flag.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% reg_indices_cell -  cell that contains the indices of each region.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% lines -  struct of all lines in map.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

% Function Outputs:
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% features_struct - 
%                    - reg_count            - number of regions.
%                    - reg_map                 - map of regions.
%                    - reg_loc_mat       -  matrix of location features of the regions.
%                    - reg_text_mat    - matrix of texture features of the regions.
%                    - reg_color_mat - matrix of color features of the regions.
%                    - reg_geom_mat    - matrix of geometry features of the regions.
%                    - reg_shape_mat - matrix of shape features of the regions.
%                    - names_list         - cell of all features names' matrices.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

% calculating general preliminary values
reg_count=length(unique(reg_map));
image_gray=rgb2gray(image);
names_list = cell(5, 1);

% calculating texture features - preliminary calculations
scales=size(filters,1);
orients=size(filters,2);
filter_num=scales*orients;
texture_features = filter_num+3;
texture_mat=zeros(texture_features,reg_count);

% building all discription's labels
texture_names=cell(texture_features,1);
text='Texture feature - abs response for gabor filter - scale';
for i=1:filter_num
    scale_num=ceil(i/orients);
    temp=mod(i,orients);
    if (temp~=0)
        orient_num=temp;
    else orient_num=orients;
    end
    texture_names{i,1}=sprintf('%s %d orient %d',text,scale_num,orient_num);
end
texture_names{filter_num+1,1}='Texture feature - mean of variables from abs response';
texture_names{filter_num+2,1}='Texture feature - argmax  of variables from abs response';
texture_names{filter_num+3,1}='Texture feature - max-median  of variables from abs response';
names_list{1} = texture_names;
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% calculating color features - preliminary calculations
color_features = 6;
R=image(:,:,1);
G=image(:,:,2);
B=image(:,:,3);
H=HSV(:,:,1);
S=HSV(:,:,2);
V=HSV(:,:,3);
color_mat=zeros(color_features,reg_count);
% building all discription's labels
color_names=cell(6,1);
color_names{1,1}='Color feature - RGB values: mean of Red';
color_names{2,1}='Color feature - RGB values: mean of Green';
color_names{3,1}='Color feature - RGB values: mean of Blue';
color_names{4,1}='Color feature - HSV values: mean of Hue';
color_names{5,1}='Color feature - HSV values: mean of Saturation';
color_names{6,1}='Color feature - HSV values: mean of Value';
names_list{2} =  color_names;
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% calculating location features - preliminary calculations
location_features = 6;
height = size(reg_map,1);
width = size(reg_map,2);
map_size=size(reg_map);
location_mat=zeros(location_features,reg_count);
% building all discription's labels
location_names = cell(location_features,1);
location_names{1} = 'Location Feature - mean of normilized X';
location_names{2} = 'Location Feature - mean of normilized Y';
location_names{3} = 'Location Feature - 10th percentile of normilized X';
location_names{4} = 'Location Feature - 10th percentile of normilized Y';
location_names{5} = 'Location Feature - 90th percentile of normilized X';
location_names{6} = 'Location Feature - 90th percentile of normilized Y';
names_list{3} =  location_names;
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% calculating geom features - preliminary calculations
geometry_features = 33;
geometry_mat=zeros(geometry_features,reg_count);
size_img=size(image_gray);

if (isempty(lines))
    geometry_mat = 0;
else
    % region_lines_mat - boolean table to see which line in each region
    region_lines_mat=zeros(length(lines),reg_count);
    %spreading lines to the regions
    for i=1:length(lines)
        line_regions=reg_map(lines(1,i).i_support,lines(1,i).j_support);
        region_lines_mat(i,unique(line_regions))=1;
    end
    %some calc to be used inside the loop
    theta_12bins=linspace(-pi,pi,13);
    theta_8bins=linspace(-pi,pi,9);
    R1=0.5*sqrt(size_img(1)^2+size_img(2)^2);
    R1_5=1.5*R1;
    R5=5*R1;
end

 % building all discription's labels
 geometry_names = cell(geometry_features,1);
 geometry_names{1,1}='3D geometry features - numnber of lines in region';
 geometry_names{2,1}='3D geometry features - precent of parallel lines in region';
 text='3D geometry features - number of inter. points over orient ';
 for i=1:12
     geometry_names{i+2,1}=sprintf('%s %d',text,i);
 end
 geometry_names{15,1}='3D geometry features - entropy';
 geometry_names{16,1}='3D geometry features - inter. points  - pct. right of center';
 geometry_names{17,1}='3D geometry features - inter. points  - pct. above center';

 text1='3D geometry features - pct. of inter. points far from center ,orient ';
 text2='3D geometry features - pct. of inter. points very far from center ,orient ';
  for i=1:8
      geometry_names{17+i,1}=sprintf('%s %d',text1,i);
      geometry_names{25+i,1}=sprintf('%s %d',text2,i);
  end
names_list{4} = geometry_names;
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% calculating shape features - preliminary calculations
shape_features=3;
shape_mat=zeros(shape_features,reg_count);
STATS = regionprops(reg_map,'Area','ConvexArea','ConvexHull');
shape_mat(3,:)= [STATS(:,1).Area] ./ [STATS(:,1).ConvexArea];

% building all discription's labels
shape_names = cell(shape_features,1);
shape_names{1} = 'Shape Feature - number of superpixels in region';
shape_names{2} = 'Shape Feature - number of sides in Convex Hull';
shape_names{3} = 'Shape Feature - num of pixels / area of Convex Hull';
names_list{5} = shape_names;
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

for reg_num=1:reg_count
    indices=reg_indices_cell{1,reg_num};
    % calculating texture features - each region
    for i=1:scales
        scale=(i-1)*orients;
        for j=1:orients
            texture_mat(scale+j,reg_num)=mean(filters{i,j}(indices));
        end
    end
    T1=texture_mat(1:filter_num,reg_num);
    texture_mat(filter_num+1,reg_num)=mean(T1);
    [maxval,maxarg]=max(T1);
    texture_mat(filter_num+2,reg_num)=maxarg;
    texture_mat(filter_num+3,reg_num)=maxval-median(T1);
    %-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    % calculating color features - each region
    % for each region, getting out all RGB and HSV values from original image
    rgb(:,1:3)=[R(indices) G(indices) B(indices)];
    hsv(:,1:3)=[H(indices) S(indices) V(indices)];
    % setting all means
    color_mat(1:3,reg_num)=mean(rgb(:,1:3));
    color_mat(4:6,reg_num)=mean(hsv(:,1:3));
    clear rgb;
    clear hsv;
    %-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    % calculating location features - each region
    [y_coordinates, x_coordinates] = ind2sub(map_size,indices);
    location_mat(1,reg_num)= mean(x_coordinates)/width;
    location_mat(2,reg_num)= mean(y_coordinates)/height;
    location_mat(3,reg_num) = prctile(x_coordinates,10)/width;
    location_mat(4,reg_num) = prctile(y_coordinates,10)/height;
    location_mat(5,reg_num) = prctile(x_coordinates,90)/width;
    location_mat(6,reg_num) = prctile(y_coordinates,90)/height;
    %-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    % calculating geom features - each region
    if (~isempty(lines))
        line_indices=find(region_lines_mat(:,reg_num)==1);
        if (isempty(line_indices))  % if no lines in region
            geometry_mat(1:geometry_features,reg_num)=0;
        else
             % how many lines in region
             geometry_mat(1,reg_num)=length(line_indices);

              % comparing all slopes to find parallel lines   
              temp_lines=lines(line_indices);
              temp_lines_a_b=cell2mat({temp_lines.a_b});
              clear temp_lines;
              slopes=temp_lines_a_b;
              slopes=round(slopes(1,:).*100);
              different_slopes=histc(slopes,unique(slopes));

              % getting pct. of parallel lines
              if (different_slopes==0)
                  geometry_mat(2,reg_num)=0;
               else
                  geometry_mat(2,reg_num)=(length(find(different_slopes~=1))/length(different_slopes));
              end

              % looking for all intersection points in region
              inter_points=lines_intersections(temp_lines_a_b);

              if (isempty(inter_points))
                  geometry_mat(3:geometry_features,reg_num)=0;

              else 
                  % center=(image width/2,image height/2 )
                  normal_points(1,:)=inter_points(1,:)-(size_img(2)/2);
                  normal_points(2,:)=inter_points(2,:)-(size_img(1)/2);

                  % calculating angle and radius for each point based on the unit
                  % circle, inside a rectangle
                  theta_points=atan2(normal_points(1,:),normal_points(2,:));
                  r_points=sqrt(normal_points(1,:).^2+normal_points(2,:).^2);
                  clear normal_points;

                  hist_12=histc(theta_points,theta_12bins)/length(theta_points);
                  % num of intersection points in each orient from 12 orients  (-pi : pi)
                  geometry_mat(3:14,reg_num)=hist_12(1:end-1);
                  % calculating entropy  = sigma(-xlogx)
                  hist_no_zero=hist_12(hist_12~=0);
                  geometry_mat(15,reg_num)=-sum(hist_no_zero(1:end).*log10(hist_no_zero(1:end)));
                  % precent of right from center - that means bins 4-9
                  geometry_mat(16,reg_num)=sum(hist_12(4:9));
                  % precent of above center - that means bins 7-12
                  geometry_mat(17,reg_num)=sum(hist_12(7:12));

                  %calculating how far are the points from center
                  far_indices= find(R1_5<=r_points & r_points<R5);
                   if (isempty(far_indices))
                       geometry_mat(18:25,reg_num)=0;
                   else
                       theta_far=theta_points(far_indices);
                       hist_far=histc(theta_far,theta_8bins)/length(theta_far);
                       % precent of all the points that are at between 1/5 radius and 5 times radius from
                       % center, at each from 8 angle's bins 
                       geometry_mat(18:25,reg_num)=hist_far(1:8);
                   end

                   very_far_indices= find(R5<=r_points);
                   if (isempty(very_far_indices))
                       geometry_mat(26:33,reg_num)=0;
                   else
                       theta_far=theta_points(very_far_indices);
                       hist_very_far=histc(theta_far,theta_8bins)/length(theta_far);
                       % same, but at least 5 times radius
                       geometry_mat(26:33,reg_num)=hist_very_far(1:8);
                   end
              end
        end
    end
    %-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    % calculating shape features - each region
    shape_mat(1,reg_num) = length(unique(seg_map(indices)));
    shape_mat(2,reg_num) = length(STATS(reg_num).ConvexHull);       
    %-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
end

% setting the output
reg_text_mat=texture_mat;
reg_loc_mat=location_mat;
reg_color_mat=color_mat;
reg_geom_mat=geometry_mat;
reg_shape_mat=shape_mat;

if (strcmp(norm_flag , 'true'))
    [reg_text_mat,reg_loc_mat,reg_color_mat,reg_geom_mat,reg_shape_mat] = normalize_data_reg(texture_mat,location_mat,color_mat,geometry_mat,shape_mat);
end
features_struct = struct('reg_count',reg_count,'reg_map',reg_map,'reg_loc_mat',reg_loc_mat,...
    'reg_text_mat',reg_text_mat,'reg_color_mat',reg_color_mat,'reg_geom_mat',...
    reg_geom_mat,'reg_shape_mat',reg_shape_mat,'names_list',{names_list});

